package cn.actitivi.helloworld;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.FileUtils;
import org.junit.Test;

public class HelloWorld {
	
	ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
	
	/**部署流程定义*/
	@Test
	public void deploymentProcessDefinition(){
		Deployment deployment = processEngine.getRepositoryService()//与流程定义和部署对象相关的Service
						.createDeployment()//创建一个部署对象
						.name("activiti入门程序")//创建一个部署名称
						.addClasspathResource("diagrams/helloworld.bpmn")//从ClassPath的资源中加载，一次只能加载一个文件
						.addClasspathResource("diagrams/helloworld.png")
						.deploy();//完成部署
		System.out.println(deployment.getId());
		System.out.println(deployment.getName());
	}
	
	/**启动流程实例*/
	@Test
	public void startProcessInstance(){
		ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的Service
						.startProcessInstanceByKey("helloworld");//使用流程定义中的key启动流程实例，key对应helloworld文件中id的属性值，使用key启动，默认是按照最新版本的流程定义启动
		System.out.println(pi.getId());//流程实例id
		System.out.println(pi.getProcessDefinitionId());//流程定义id
	}
	
	/**查询当前人的个人任务*/
	@Test
	public void findMyPersonalTask(){
		String assignee = "王五";
		List<Task> list = processEngine.getTaskService()//与正在执行的任务管理相关的Service
						.createTaskQuery()//创建任务查询对象
						.taskAssignee(assignee)//指定个人任务查询，指定办理人
						.list();
		if(list!=null&&list.size()>0){
			for (Task task : list) {
				System.out.println("任务id"+task.getId());
				System.out.println("任务名称"+task.getName());
				System.out.println("任务的创建时间"+task.getCreateTime());
				System.out.println("任务的办理人"+task.getAssignee());
				System.out.println("流程实例id"+task.getProcessInstanceId());
				System.out.println("执行对象id"+task.getExecutionId());
				System.out.println("流程定义id"+task.getProcessDefinitionId());
			}
		}
	}
	
	/**完成任务*/
	@Test
	public void completeMyPersonalTask(){
		//任务id
		String taskId = "7502";
		processEngine.getTaskService()//与正在执行的任务管理相关的Service
						.complete(taskId);
		System.out.println("完成任务：任务id：" + taskId);
	}
	
	
	/**部署流程定义（zip格式）*/
	@Test
	public void deployZIP(){
		//获得上传文件的输入流程
		InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("diagrams/helloworld.zip");
		ZipInputStream zipInputStream = new ZipInputStream(inputStream);
		
		//获取仓库服务，从类路径下完成部署
		Deployment deploy = processEngine.getRepositoryService()
						.createDeployment()
						.name("请假流程")//添加部署规则的显示别名
						.addZipInputStream(zipInputStream)//使用zip输入流完成部署
						.deploy();//完成发布
		
		System.out.println(deploy.getId()+"         "+deploy.getName());
		
	}
	
	/**
	 * 查看流程定义
	 * 		id:{key}:{version}:{随机值}
	 * 		name: 对应流程文件process节点的name属性
	 * 		key: 对应流程文件process节点的id属性
	 * 		version: 发布时自动生成的。如果是第一发布的流程，version默认从1开始；
	 * 				  如果当前流程引擎中已存在相同key的流程，则找到当前key对应的最高版本号，在最高版本号上加1
	 */
	@Test
	public void queryProcessDefinition(){
		//获取仓库服务对象，使用版本升序排列，查询列表
		List<ProcessDefinition> pdList = processEngine.getRepositoryService()
						.createProcessDefinitionQuery()
						//添加条件
						//.processDefinitionName("")
						//.processDefinitionId("")
						//.processDefinitionKey("")
						//排序
						.orderByProcessDefinitionVersion().asc()
						//查询的结果集
						//.count()//返回结果集的数量
						//.listPage(firstResult, maxResults)//分页查询
						//.singleResult()//唯一结果集
						.list();//总的结果集
		
		for (ProcessDefinition pd : pdList) {
			System.out.println("id:"+pd.getId());
			System.out.println("name:"+pd.getName());
			System.out.println("key:"+pd.getKey());
			System.out.println("version:"+pd.getVersion());
			System.out.println("resourceName:"+pd.getDiagramResourceName());
		}
	}
	
	/**删除流程定义*/
	@Test
	public void deleteDeployment(){
		//删除发布信息
		String deploymentId = "5001";
		//获取仓库服务对象
		RepositoryService repositoryService = processEngine.getRepositoryService();
		//普通删除，如果当前规则下有正在执行的流程，则抛异常
		//repositoryService.deleteDeployment(deploymentId);
		//联级删除，会删除和当前规则相关的所有信息，正在执行的信息，也包括历史信息
		//相当于: repositoryService.deleteDeploymentCascade(deploymentId);
		repositoryService.deleteDeployment(deploymentId, true);
	}
	
	/**查看流程附件（查看流程图片）*/
	@Test
	public void viewImage() throws IOException{
		//从仓库中找到需要展示的文件
		String deploymentId = "1";
		List<String> resourceNames = processEngine.getRepositoryService()
						.getDeploymentResourceNames(deploymentId);
		String imageName = null;
		for (String name : resourceNames) {
			System.out.println("name:"+name);
			if(name.indexOf(".png")>=0){
				imageName = name;
			}
		}
		
		System.out.println("imageName:"+imageName);
		if(imageName!=null){
			File file = new File("e:/"+imageName);
			//通过部署id和文件名称得到文件的输入流
			InputStream inputStream = processEngine.getRepositoryService()
							.getResourceAsStream(deploymentId, imageName);
			FileUtils.copyInputStreamToFile(inputStream, file);
			
		}
	}
	
	/**查询最新版本的流程定义*/
	@Test
	public void queryAllletestVersions(){
		//查询，把最大的版本都排到后面
		List<ProcessDefinition> list = processEngine.getRepositoryService()
						.createProcessDefinitionQuery()
						.orderByProcessDefinitionVersion().asc()
						.list();
		//过滤出最新的版本
		Map<String,ProcessDefinition> map = new LinkedHashMap<String,ProcessDefinition>();
		for (ProcessDefinition pd : list) {
			map.put(pd.getId(), pd);
		}
		
		//显示
		for (ProcessDefinition pd : map.values()) {
			System.out.println("id:"+pd.getId()//格式：（key）-（version）
			+",name:"+pd.getName()//.jpdl.xml根元素name的属性值
			+",key:"+pd.getKey()//.jpdl.xml根元素的key属性的值，如果不写，默认为name属性的值
			+",version:"+pd.getVersion()//默认自动维护，第1个是1，以后相同的key都会自动加1
			+",deploymentId:"+pd.getDeploymentId()//所属的某个deployment的对象
			);
		}
	}
	
	/**删除（使用流程定义的key）*/
	@Test
	public void deleteByKey(){
		//查询制定key的所有版本的流程定义
		List<ProcessDefinition> list = processEngine.getRepositoryService()
						.createProcessDefinitionQuery()
						.processDefinitionKey("helloworld")
						.list();
		//循环删除
		for (ProcessDefinition processDefinition : list) {
			processEngine.getRepositoryService()
							.deleteDeployment(processDefinition.getDeploymentId(),true);
		}
		
		System.out.println("删除成功！");
	}
	
	/**查看流程状态（判断流程是正在执行，还是已经结束）*/
	@Test
	public void queryProcessState(){
		String processInstanceId = "10001";
		//通过流程实例ID查询流程实例
		ProcessInstance pi = processEngine.getRuntimeService()
						.createProcessInstanceQuery()//创建流程实例查询，查询正在执行的流程实例
						.processInstanceId(processInstanceId)//按照流程实例ID查询
						.singleResult();//返回唯一结果集
		if(pi!=null){
			System.out.println("当前流程在："+pi.getActivityId());
		}else{
			System.out.println("流程已经结束！");
		}
						
		
	}
	
	/**查询历史任务*/
	@Test
	public void queryHistoryTask(){
		//历史任务办理人
		String taskAssignee = "张三";
		//通过流程实例ID查询流程实例
		List<HistoricTaskInstance> list = processEngine.getHistoryService()
						.createHistoricTaskInstanceQuery()//创建历史任务查询
						.taskAssignee(taskAssignee)//指定办理人查询历史任务
						.list();
		
		if(list!=null&&list.size()>0){
			for (HistoricTaskInstance task : list) {
				System.out.println("任务id："+task.getId());
				System.out.println("流程实例id："+task.getProcessInstanceId());
				System.out.println("任务办理人："+task.getAssignee());
				System.out.println("执行对象id："+task.getExecutionId());
				System.out.println(task.getStartTime()+"   "+task.getEndTime()+"    "+task.getDurationInMillis());
			}
		}
	}
	
	/**查询历史流程实例*/
	@Test
	public void queryHistoryProcessInstance(){
		String historyProcessInstance = "10001";
		HistoricProcessInstance singleResult = processEngine.getHistoryService()
						.createHistoricProcessInstanceQuery()
						.processInstanceId(historyProcessInstance)
						.singleResult();
		
		System.out.println("流程定义ID:"+singleResult.getProcessDefinitionId());
	}
	
	/**流程变量的设置和获取场景*/
	/*@Test
	public void setAndGetvariables(){
		RuntimeService runtimeService = processEngine.getRuntimeService();
		TaskService taskService = processEngine.getTaskService();
		//====================================================
		//设置变量的方法
		//通过Execution设置一个变量
		runtimeService.setVariable(executionId, name, value);
		//通过Execution设置多个变量
		runtimeService.setVariables(executionId, variablesMap);
		//通过Task设置一个变量
		taskService.setVariable(taskId, variableName, value);
		//通过Task设置多个变量
		taskService.setVariables(taskId, variablesMap);
		//在启动实例的时，同时设置一些变量
		runtimeService.startProcessInstanceByKey(processInstanceKey, variables);
		//在完成实例时，同时设置一些变量
		taskService.complete(taskId,variables);
		//=====================================================
		//获取变量的方法
		//通过Execution获取一个变量
		runtimeService.getVariable(executionId, variableName);
		//通过Execetion获取所有变量信息，存放在Map集合中
		runtimeService.getVariables(executionId);
		//通过Execetion获取指定流程变量名称的信息，存放到Map集合中
		runtimeService.getVariablesLocal(executionId, variablesName);
		
		//通过Task获取一个变量
		taskService.getVariable(taskId, variableName);
		//通过Task获取所有变量信息，存放在Map集合中
		taskService.getVariables(taskId);
		//通过Task获取指定流程变量名称的变量的信息，存放到Map集合
		taskService.getVariable(taskId, variablesName);
	}*/
	
	/**查询历史的流程变量*/
	@Test
	public void getHisVariables(){
		List<HistoricVariableInstance> list = processEngine.getHistoryService()
						.createHistoricVariableInstanceQuery()
						.variableName("请假天数")//指定流程变量名称查询
						.list();
		
		if( list!=null&&list.size()>0 ){
			for (HistoricVariableInstance hvi : list) {
				System.out.println(hvi.getVariableName()+"       " + hvi.getValue());
			}
		}
		
		
	}
	
	/**历史流程实例查看（查找按照某个规则一共执行了多少次流程）*/
	@Test
	public void queryHistoricProcessInstance(){
		//获取历史流程实例，返回历史流程实例的集合
		List<HistoricProcessInstance> list = processEngine.getHistoryService()
						.createHistoricProcessInstanceQuery()//创建历史流程实例查询
						.processDefinitionKey("helloworld")//按照流程定义的key查询
						.orderByProcessInstanceStartTime().desc()//按照流程开始时间降序排列
						.list();
		
		for (HistoricProcessInstance hpi : list) {
			System.out.println("pid:"+hpi.getId());
			System.out.println("pdid:"+hpi.getProcessDefinitionId());
			System.out.println("startTime:"+hpi.getStartTime());
			System.out.println("endTime:"+hpi.getEndTime());
			System.out.println("duration:"+hpi.getDurationInMillis());
			
		}
	}
	
	/**历史活动查看（某一次流程的执行经历的多少步）*/
	@Test
	public void queryHistoricActivityInstance(){
		String processInstanceId = "10001";
		List<HistoricActivityInstance> list = processEngine.getHistoryService()
						.createHistoricActivityInstanceQuery()
						.processInstanceId(processInstanceId)
						//.listPage(firstResult, maxResult)//分页条件
						.orderByHistoricActivityInstanceEndTime().asc()//排序条件
						.list();//执行查询
		
		for (HistoricActivityInstance hai : list) {
			System.out.println("activityId:"+hai.getActivityId());
			System.out.println("name:"+hai.getActivityName());
			System.out.println("type:"+hai.getActivityType());
			System.out.println("pId:"+hai.getProcessInstanceId());
			System.out.println("assignee:"+hai.getAssignee());
			System.out.println("startTime:"+hai.getStartTime());
			System.out.println("endTime:"+hai.getEndTime());
			System.out.println("duration:"+hai.getDurationInMillis());
			System.out.println("-------------------------------------");
			
		}
	}
	
	/**历史任务查看（某一次流程的执行经历的多少任务节点）*/
	@Test
	public void queryHistoricTack(){
		String processInstanceId = "10001";
		List<HistoricTaskInstance> list = processEngine.getHistoryService()
						.createHistoricTaskInstanceQuery()//创建历史任务的查询
						.processInstanceId(processInstanceId)//使用流程实例id查询
						.orderByHistoricTaskInstanceEndTime().asc()//排序条件
						.list();
		for (HistoricTaskInstance hti : list) {
			System.out.println("taskId:" + hti.getId());
			System.out.println("name:" + hti.getName());
			System.out.println("pdId:" + hti.getProcessDefinitionId());
			System.out.println("pId:" + hti.getProcessInstanceId());
			System.out.println("assignee:" + hti.getAssignee());
			System.out.println("startTime:" + hti.getStartTime());
			System.out.println("endTime:" + hti.getEndTime());
			System.out.println("duration:" + hti.getDurationInMillis());
			System.out.println("-------------------------------------");
		}
	}
	
	/**某一次流程的执行时设置的流程变量*/
	@Test
	public void queryHistoricVariables(){
		String processInstanceId = "10001";
		List<HistoricVariableInstance> list = processEngine.getHistoryService()
						.createHistoricVariableInstanceQuery()
						.processInstanceId(processInstanceId)
						.orderByVariableName().asc()
						.list();
		for (HistoricVariableInstance hvi : list) {
			System.out.println("piId:"+hvi.getProcessInstanceId());
			System.out.println("variablesName:"+hvi.getVariableName());
			System.out.println("variablesValue:"+hvi.getValue());
			System.out.println("-------------------------------------");
		}
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
